The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.
Changes 013
MANIFEST 12
META.yml 11
Makefile.PL 54
lib/MooseX/Role/Parameterized/Extending.pod 040
lib/MooseX/Role/Parameterized/Meta/Parameter.pm 11
lib/MooseX/Role/Parameterized/Meta/Role/Parameterizable.pm 36
lib/MooseX/Role/Parameterized/Meta/Role/Parameterized.pm 11
lib/MooseX/Role/Parameterized/Meta/Trait/Parameterized.pm 11
lib/MooseX/Role/Parameterized/Parameters.pm 11
lib/MooseX/Role/Parameterized/Tutorial.pod 1218
lib/MooseX/Role/Parameterized.pm 47
t/003-apply.t 112
t/019-custom-metaclass.t 045
t/200-curried-parameterized-role.t 430
15 files changed (This is a version diff) 74152
@@ -1,5 +1,18 @@
 Changes for MooseX-Role-Parameterized
 
+0.18  March 10, 2010
+    * Improve the error message when you leave off the role {} block
+      http://stackoverflow.com/questions/2418177/moose-and-error-messages-the-sun-and-the-moon/2418429
+
+0.17  February 11, 2010
+    * MANIFEST fixes (Karen Etheridge)
+
+0.16  February 4, 2010
+    * Allow specifying custom metaclasses for parameterized
+      roles (Oliver Charles)
+
+    * Documentation improvements (Oliver Charles, Sartak)
+
 0.15  January 5, 2010
     * Move the guts of MXRPMR::Parameterized into a trait. See
       http://www.nntp.perl.org/group/perl.moose/2010/01/msg1294.html (Sartak)
@@ -8,6 +8,7 @@ inc/Module/Install/Metadata.pm
 inc/Module/Install/Win32.pm
 inc/Module/Install/WriteAll.pm
 lib/MooseX/Role/Parameterized.pm
+lib/MooseX/Role/Parameterized/Extending.pod
 lib/MooseX/Role/Parameterized/Meta/Parameter.pm
 lib/MooseX/Role/Parameterized/Meta/Role/Parameterizable.pm
 lib/MooseX/Role/Parameterized/Meta/Role/Parameterized.pm
@@ -35,9 +36,9 @@ t/015-compose-keywords.t
 t/016-trait.t
 t/017-current_metaclass.t
 t/018-parameter-roles.t
+t/019-custom-metaclass.t
 t/100-erroneous-keywords.t
 t/101-alias-excludes.t
 t/102-nested.t
 t/150-composite-role-application.t
-t/200-curried-parameterized-role.t
 t/lib/Bar.pm
@@ -25,4 +25,4 @@ requires:
   perl: 5.8.1
 resources:
   license: http://dev.perl.org/licenses/
-version: 0.15
+version: 0.18
@@ -6,11 +6,10 @@ name           'MooseX-Role-Parameterized';
 all_from       'lib/MooseX/Role/Parameterized.pm';
 githubmeta;
 
-requires       'Moose' => '0.78';
-test_requires  'Test::Moose';
-test_requires  'Test::More' => '0.88';
-
-build_requires 'Test::Exception' => '0.27';
+requires      'Moose' => '0.78';
+test_requires 'Test::Moose';
+test_requires 'Test::More' => '0.88';
+test_requires 'Test::Exception' => '0.27';
 
 WriteAll;
 
@@ -0,0 +1,40 @@
+=pod
+
+=head1 NAME
+
+MooseX::Role::Parameterized::Extending - extending MooseX::Role::Parameterized roles
+
+=head1 DESCRIPTION
+
+There are heaps of useful modules in the MooseX namespace that you can use to
+make your roles more powerful. However, they do not always work out of the box
+with MooseX::Role::Parameterized, but it's fairlystraight forward to achieve
+the functionality you desire.
+
+MooseX::Role::Parameterized was designed to be extensible, and it is now
+possible to apply custom traits to the generated role, giving them the
+functionality provided in MooseX modules. In this example, we will look at
+applying the fake trait 'MooseX::MagicRole' to a parameterized role.
+
+The first we need to do is define a new metaclass for our parameterized role.
+To get MooseX::Role::Parameterized to apply this metaclass to our roles, we
+need a little bit of glue first:
+
+    package MyApp::Meta::Role::Parameterizable;
+    use Moose;
+    extends 'MooseX::Role::Parameterized::Meta::Role::Parameterizable';
+    sub parameterized_role_metaclass { 'MyApp::Meta::Role::Parameterized' }
+
+Now we can take advantage of this by specifying our glue metaclass to
+MooseX::Role::Parameterized:
+
+    package MyApp::Role;
+    use MooseX::Role::Parameterized -metaclass => 'MyApp::Meta::Role::Parameterizable';
+
+    role {
+    }
+
+And there you go! MyApp::Role now has the MooseX::MagicRole trait applied.
+
+=cut
+
@@ -2,7 +2,7 @@ package MooseX::Role::Parameterized::Meta::Parameter;
 use Moose;
 extends 'Moose::Meta::Attribute';
 
-our $VERSION = '0.15';
+our $VERSION = '0.18';
 
 # This doesn't actually do anything because _process_options does not consult
 # the default value of "is". hrm.
@@ -2,7 +2,7 @@ package MooseX::Role::Parameterized::Meta::Role::Parameterizable;
 use Moose;
 extends 'Moose::Meta::Role';
 
-our $VERSION = '0.15';
+our $VERSION = '0.18';
 
 use MooseX::Role::Parameterized::Meta::Role::Parameterized;
 use MooseX::Role::Parameterized::Meta::Parameter;
@@ -76,10 +76,13 @@ sub generate_role {
                    ? $args{parameters}
                    : $self->construct_parameters(%{ $args{parameters} });
 
-    confess "A role generator is required to generate roles"
+    confess "A role generator is required to apply parameterized roles (did you forget the 'role { ... }' block in your parameterized role '".$self->name."'?)"
         unless $self->has_role_generator;
 
-    my $role = $self->parameterized_role_metaclass->create_anon_role(
+    my $parameterized_role_metaclass = $self->parameterized_role_metaclass;
+    Class::MOP::load_class($parameterized_role_metaclass);
+
+    my $role = $parameterized_role_metaclass->create_anon_role(
         genitor    => $self,
         parameters => $parameters,
     );
@@ -3,7 +3,7 @@ use Moose;
 extends 'Moose::Meta::Role';
 with 'MooseX::Role::Parameterized::Meta::Trait::Parameterized';
 
-our $VERSION = '0.15';
+our $VERSION = '0.18';
 
 __PACKAGE__->meta->make_immutable;
 no Moose;
@@ -1,7 +1,7 @@
 package MooseX::Role::Parameterized::Meta::Trait::Parameterized;
 use Moose::Role;
 
-our $VERSION = '0.15';
+our $VERSION = '0.18';
 
 use MooseX::Role::Parameterized::Parameters;
 
@@ -1,7 +1,7 @@
 package MooseX::Role::Parameterized::Parameters;
 use Moose;
 
-our $VERSION = '0.15';
+our $VERSION = '0.18';
 
 __PACKAGE__->meta->make_immutable;
 no Moose;
@@ -13,7 +13,7 @@ L<Moose::Cookbook::Roles::Recipe1> for an introduction to L<Moose::Role>.
 While combining roles affords you a great deal of flexibility, individual roles
 have very little in the way of configurability. Core Moose provides C<alias>
 for renaming methods and C<excludes> for ignoring methods. These options are
-primarily (perhaps solely) for disambiguating role conflicts. See
+primarily (perhaps solely) for resolving role conflicts. See
 L<Moose::Cookbook::Roles::Recipe2> for more about C<alias> and C<excludes>.
 
 Because roles serve many different masters, they usually provide only the least
@@ -22,7 +22,7 @@ configurability than C<alias> and C<excludes> is required. Perhaps your role
 needs to know which method to call when it is done. Or what default value to
 use for its C<url> attribute.
 
-Parameterized roles offer exactly this solution.
+Parameterized roles offer a solution to these (and other) kinds of problems.
 
 =head1 USAGE
 
@@ -50,8 +50,9 @@ immediately after the role they belong to:
 =head3 C<parameter>
 
 Inside your parameterized role, you specify a set of parameters. This is
-exactly like specifying the attributes of a class. Instead of C<has> you use
-the keyword C<parameter>, but your parameters can use any options to C<has>.
+exactly like specifying the attributes of a class. Instead of L<Moose/has> you
+use the keyword C<parameter>, but your parameters can use any options to
+C<has>.
 
     parameter 'delegation' => (
         isa       => 'HashRef|ArrayRef|RegexpRef',
@@ -61,15 +62,20 @@ the keyword C<parameter>, but your parameters can use any options to C<has>.
 You do have to declare what parameters you accept, just like you have to
 declare what attributes you accept for regular Moose objects.
 
+One departure from C<has> is that we create a reader accessor for you by
+default. In other words, we assume C<< is => 'ro' >>. If you do not want an
+accessor, you can use C<< is => 'bare' >>.
+
 =head3 C<role>
 
 C<role> takes a block of code that will be used to generate your role with its
-parameters bound. Here is where you declare parameterized components: use
-C<has>, method modifiers, and so on. The C<role> block receives an argument,
-which contains the parameters specified by C<with>. You can access the
-parameters just like regular attributes on that object.
+parameters bound. Here is where you declare components that depend on
+parameters. You can declare attributes, methods, modifiers, etc. The first
+argument to the C<role> is an object containing the parameters specified by
+C<with>. You can access the parameters just like regular attributes on that
+object.
 
-Each time you compose this parameterized role, the role {} block will be
+Each time you compose this parameterized role, the C<role {}> block will be
 executed. It will receive a new parameter object and produce an entirely new
 role. That's the whole point, after all.
 
@@ -112,9 +118,9 @@ can now also choose type, default value, whether it's required, B<traits>, etc.
 
 =item Inform a role of your class' attributes and methods
 
-Core roles can require only methods with specific names. Now your roles can
-require that you specify a method name you wish the role to instrument, or
-which attributes to dump to a file.
+Core roles can only require methods with specific names chosen by the role. Now
+your roles can demand that the class specifies a method name you wish the role to
+instrument, or which attributes to dump to a file.
 
     parameter instrument_method => (
         isa      => 'Str',
@@ -7,7 +7,7 @@ use Scalar::Util 'blessed';
 
 use MooseX::Role::Parameterized::Meta::Role::Parameterizable;
 
-our $VERSION = '0.15';
+our $VERSION = '0.18';
 our $CURRENT_METACLASS;
 
 Moose::Exporter->setup_import_methods(
@@ -43,10 +43,10 @@ sub role (&) {
 
 sub init_meta {
     my $self = shift;
+    my %options = @_;
+    $options{metaclass} ||= 'MooseX::Role::Parameterized::Meta::Role::Parameterizable';
 
-    return Moose::Role->init_meta(@_,
-        metaclass => 'MooseX::Role::Parameterized::Meta::Role::Parameterizable',
-    );
+    return Moose::Role->init_meta(%options);
 }
 
 sub has {
@@ -226,6 +226,9 @@ There are many possible implementations for parameterized roles (hopefully with
 a consistent enough API); I believe this to be the easiest and most flexible
 design. Coincidentally, Pugs originally had an eerily similar design.
 
+See L<MooseX::Role::Parameterized::Extending> for some tips on how to extend
+this module.
+
 =head2 Why a parameters object?
 
 I've been asked several times "Why use a parameter I<object> and not just a
@@ -1,7 +1,7 @@
 #!/usr/bin/env perl
 use strict;
 use warnings;
-use Test::More tests => 21;
+use Test::More tests => 22;
 use Test::Exception;
 
 my %args;
@@ -136,6 +136,17 @@ throws_ok {
     };
 } qr/^Attribute \(format\) does not pass the type constraint/;
 
+throws_ok {
+    package MyRole::Sans::Block;
+    use MooseX::Role::Parameterized;
+
+    parameter 'foo';
+
+    package MyClass::Error::BlocklessRole;
+    use Moose;
+    with 'MyRole::Sans::Block' => {};
+} qr/^\QA role generator is required to apply parameterized roles (did you forget the 'role { ... }' block in your parameterized role 'MyRole::Sans::Block'?)\E/;
+
 sub cant_ok {
     local $Test::Builder::Level = $Test::Builder::Level + 1;
     my $instance = shift;
@@ -0,0 +1,45 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+use Test::More tests => 1;
+use Test::Moose;
+
+do {
+    package MyTrait;
+    use Moose::Role;
+};
+
+BEGIN {
+    do {
+        package Parameterized;
+        use Moose;
+        extends 'Moose::Meta::Role';
+        with 'MooseX::Role::Parameterized::Meta::Trait::Parameterized';
+        with 'MyTrait';
+    };
+
+    do {
+        package Parameterizable;
+        use Moose;
+        extends 'MooseX::Role::Parameterized::Meta::Role::Parameterizable';
+        sub parameterized_role_metaclass { 'Parameterized' }
+    };
+}
+
+do {
+    package MyRole;
+    use MooseX::Role::Parameterized -metaclass => 'Parameterizable';
+
+    role {
+        my ($params, %extra) = @_;
+        ::does_ok($extra{operating_on}, 'MyTrait', 'parameterized role should do the MyTrait trait');
+    }
+};
+
+do {
+    package MyClass;
+    use Moose;
+    with 'MyRole';
+};
+
+MyClass->new;
@@ -1,43 +0,0 @@
-#!/usr/bin/env perl
-use strict;
-use warnings;
-use Test::More skip_all => "not implemented yet";
-
-do {
-    package YAPC;
-    use MooseX::Role::Parameterized;
-
-    parameter organizer => (
-        isa      => 'Str',
-        required => 1,
-    );
-
-    parameter location => (
-        isa      => 'Str',
-        required => 1,
-    );
-
-    role {
-        my $p = shift;
-
-        method describe => sub {
-            return sprintf 'organized by %s in %s',
-                $p->organizer,
-                $p->location;
-        };
-    };
-};
-
-do {
-    package YAPC::Asia;
-    use MooseX::Role::Parameterized;
-
-    # This can't work sanely; if you want the role to be parameterized you need
-    # to declare it as such
-#    use Moose::Role;
-
-    with 'YAPC' => {
-        location => 'Tokyo',
-    };
-};
-